package cn.mw.cmdb.virtualization.service.handler;

import cn.mw.cmdb.entity.InstanceInfo;
import cn.mw.cmdb.param.InstanceSearchParam;
import cn.mw.cmdb.service.impl.CmdbServiceManage;
import cn.mw.cmdb.service.impl.InstanceServiceImpl;
import cn.mw.cmdb.virtualization.annotations.VirtualizationAlias;
import cn.mw.cmdb.virtualization.constant.MwVirtualizationConstant;
import cn.mw.cmdb.virtualization.dto.ItemLatestConvertDto;
import cn.mw.cmdb.virtualization.dto.unicloud.UniCloudVsWitchDto;
import cn.mw.cmdb.virtualization.enums.UniCloudVsWitchForwardingModelType;
import cn.mw.cmdb.virtualization.enums.UniCloudVsWitchNetWorkType;
import cn.mw.cmdb.virtualization.param.VirtualizationParam;
import cn.mw.main.api.common.ZabbixDubboService;
import cn.mw.microMonitorCommon.constants.ZabbixApiConstants;
import cn.mw.microMonitorCommon.entity.UnitResult;
import cn.mw.microMonitorCommon.entity.zabbix.MWZabbixAPIResult;
import cn.mw.microMonitorCommon.enums.UnicloudTypeEnum;
import cn.mw.microMonitorCommon.util.UnitUtil;
import com.alibaba.fastjson.JSONArray;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @description 紫光云虚拟交换机处理
 */
@Component
@Slf4j
public class UniCloudVsWitchHandler {

    private final String NETWORK_TYPE = "netWorkType";
    private final String PHYSICS = "physics";
    private final String SUBNET_MASK = "subnetMask";
    private final String GATEWAY = "gateway";
    private final String FORWARDING_MODE = "forwardingMode";

    @DubboReference(check = false, timeout = 120000)
    private ZabbixDubboService zabbixDubboService;

    public List<UniCloudVsWitchDto> getUniCloudVsWitchInfo(VirtualizationParam param, CmdbServiceManage cmdbServiceManage) throws Exception {
        String vmType = param.getVmType();
        UnicloudTypeEnum unicloudTypeEnum = UnicloudTypeEnum.getUnicloudTypeEnumByType(vmType);
        List<UniCloudVsWitchDto> vsWitchDtoList = getVsWitchInstance(unicloudTypeEnum, param, cmdbServiceManage);
        if(CollectionUtils.isEmpty(vsWitchDtoList) || param.getServerId() == null){
            return vsWitchDtoList;
        }
        List<UniCloudVsWitchDto> vsWitchDtos = getMonitorInfo(vsWitchDtoList, param);
        dataHandler(vsWitchDtos);
        return vsWitchDtos;
    }


    private void dataHandler(List<UniCloudVsWitchDto> vsWitchDtos){
        if(CollectionUtils.isEmpty(vsWitchDtos)){
            return;
        }
        for (UniCloudVsWitchDto vsWitchDto : vsWitchDtos) {
            String vSwitchBandWidth = vsWitchDto.getVSwitchBandWidth();
            if(StringUtils.isNotEmpty(vSwitchBandWidth)){
                String[] split = vSwitchBandWidth.split("_");
                UnitResult result = UnitUtil.getConvertedValue(new BigDecimal(split[0]), split[1]);
                if(result != null){
                    vsWitchDto.setVSwitchBandWidth(result.getValue()+result.getUnits());
                }
            }
        }
    }

    /**
     * 获取监控数据
     * @param vsWitchDtoList
     * @param param
     * @return
     * @throws IllegalAccessException
     */
    private List<UniCloudVsWitchDto> getMonitorInfo(List<UniCloudVsWitchDto> vsWitchDtoList,VirtualizationParam param) throws IllegalAccessException {
        List<UniCloudVsWitchDto> uniCloudVsWitchDtos = new ArrayList<>();
        List<String> hostIds = vsWitchDtoList.stream().filter(item -> StringUtils.isNotEmpty(item.getHostId())).map(s -> s.getHostId()).collect(Collectors.toList());
        //查询zabbix数据
        MWZabbixAPIResult result = zabbixDubboService.getZabbixApiResult(ZabbixApiConstants.ITEM_GET_BY_SEARCH, param.getServerId(), MwVirtualizationConstant.VS_WITCH_IETMS, hostIds);
        if(result == null || result.isFail()){
            return vsWitchDtoList;
        }
        List<ItemLatestConvertDto> latestConvertDtos = JSONArray.parseArray(String.valueOf(result.getData()), ItemLatestConvertDto.class);
        if(CollectionUtils.isEmpty(latestConvertDtos)){
            return vsWitchDtoList;
        }
        Map<String, List<ItemLatestConvertDto>> hostItemMap = latestConvertDtos.stream().collect(Collectors.groupingBy(item -> item.getHostid()));
        Map<String, UniCloudVsWitchDto> baseDtoMap = vsWitchDtoList.stream().collect(Collectors.toMap(s -> s.getHostId(), s -> s));
        for (String hostId : baseDtoMap.keySet()) {
            List<ItemLatestConvertDto> dtos = hostItemMap.get(hostId);
            UniCloudVsWitchDto vsWitchDto = baseDtoMap.get(hostId);
            if(hostItemMap.get(hostId) == null){
                uniCloudVsWitchDtos.add(vsWitchDto);
                continue;
            }
            setFieldInfo(UniCloudVsWitchDto.class,vsWitchDto,dtos);
            uniCloudVsWitchDtos.add(vsWitchDto);

        }
        return uniCloudVsWitchDtos;
    }

    /**
     * 获取实例数据
     * @param unicloudTypeEnum
     * @param param
     * @param cmdbServiceManage
     * @return
     * @throws Exception
     */
    private List<UniCloudVsWitchDto>  getVsWitchInstance(UnicloudTypeEnum unicloudTypeEnum,VirtualizationParam param,CmdbServiceManage cmdbServiceManage) throws Exception {
        List<UniCloudVsWitchDto> uniCloudVsWitchDtos = new ArrayList<>();
        InstanceServiceImpl service = (InstanceServiceImpl) cmdbServiceManage.getModelService(InstanceServiceImpl.ID);
        InstanceSearchParam instanceSearchParam = new InstanceSearchParam();
        Map data = new HashMap();
        switch (unicloudTypeEnum){
            case CLUSTER:
                data.put(MwVirtualizationConstant.CLUSTER_ID, param.getDataId().split("_")[1]);
                break;
            case HOST:
                data.put(MwVirtualizationConstant.HOST_ID, param.getDataId().split("_")[1]);
        }
        data.put(MwVirtualizationConstant.VM_TYPE, UnicloudTypeEnum.VS_WITCH.getType());
        instanceSearchParam.setData(data);
        instanceSearchParam.convert();
        List<InstanceInfo> instanceInfoList = service.doSelectList(instanceSearchParam);
        if(CollectionUtils.isEmpty(instanceInfoList)){
            return uniCloudVsWitchDtos;
        }
        for (InstanceInfo instanceInfo : instanceInfoList) {
            UniCloudVsWitchDto vsWitchDto = new UniCloudVsWitchDto();
            Map<String, Object> infoData = instanceInfo.getData();
            if(infoData == null){
                continue;
            }
            if(infoData.containsKey(MwVirtualizationConstant.TYPE_ID)){
                vsWitchDto.setHostId(infoData.get(MwVirtualizationConstant.TYPE_ID).toString());
            }
            if(infoData.containsKey(MwVirtualizationConstant.VM_TYPE)){
                vsWitchDto.setVmType(infoData.get(MwVirtualizationConstant.VM_TYPE).toString());
            }
            if(infoData.containsKey(NETWORK_TYPE)){
                Object networkType = infoData.get(NETWORK_TYPE);
                if(networkType != null){
                    UniCloudVsWitchNetWorkType netWorkType = UniCloudVsWitchNetWorkType.vsWitchNetWorkType(networkType.toString());
                    vsWitchDto.setNetWorkType(netWorkType.getValue());
                }
            }
            if(infoData.containsKey(PHYSICS)){
                Object physics = infoData.get(PHYSICS);
                if(physics != null){
                    vsWitchDto.setPhysics(physics.toString());
                }
            }
            if(infoData.containsKey(SUBNET_MASK)){
                Object subnetMask = infoData.get(SUBNET_MASK);
                if(subnetMask != null){
                    vsWitchDto.setSubnetMask(subnetMask.toString());
                }
            }
            if(infoData.containsKey(GATEWAY)){
                Object gateway = infoData.get(GATEWAY);
                if(gateway != null){
                    vsWitchDto.setGateway(gateway.toString());
                }
            }
            if(infoData.containsKey(FORWARDING_MODE)){
                Object forwardingMode = infoData.get(FORWARDING_MODE);
                if(forwardingMode != null){
                    UniCloudVsWitchForwardingModelType forwardingModelType = UniCloudVsWitchForwardingModelType.forwardingModelType(forwardingMode.toString());
                    vsWitchDto.setForwardingMode(forwardingModelType.getValue());
                }
            }
            vsWitchDto.setInBandIp(instanceInfo.getInBandIp());
            vsWitchDto.setInstanceName(instanceInfo.getInstanceName());
            vsWitchDto.setInstanceId(instanceInfo.getId());
            uniCloudVsWitchDtos.add(vsWitchDto);
        }
        return uniCloudVsWitchDtos;
    }

    private void setFieldInfo(Class cls,Object obj,List<ItemLatestConvertDto> convertDtos) throws IllegalAccessException {
        for (ItemLatestConvertDto convertDto : convertDtos) {
            String name = convertDto.getName();
            if(name.contains("[")){
                name = name.split("]")[1];
            }
            Field[] fields = cls.getDeclaredFields();
            for (Field field : fields) {
                if(!field.isAnnotationPresent(VirtualizationAlias.class)){continue;}
                VirtualizationAlias fieldAnnotation = field.getAnnotation(VirtualizationAlias.class);
                String itemName = fieldAnnotation.itemName();
                if(StringUtils.isEmpty(itemName)){continue;}
                String[] itemNames = itemName.split(",");
                if(!Arrays.asList(itemNames).contains(name)){continue;}
                field.setAccessible(true);
                Object value = field.get(obj);
                String lastvalue = convertDto.getLastvalue();
                Boolean numeric = isNumeric(lastvalue);
                if(!numeric){
                    field.set(obj,lastvalue);
                    continue;
                }
                if(StringUtils.isNotEmpty(convertDto.getUnits())){
                    if(value != null){
                        String strValue = value.toString().split("_")[0];
                        field.set(obj, new BigDecimal(lastvalue).add(new BigDecimal(strValue))+"_"+convertDto.getUnits());
                    }else{
                        field.set(obj,lastvalue+"_"+convertDto.getUnits());
                    }
                }else{
                    if(value != null){
                        String strValue = value.toString().split("_")[0];
                        field.set(obj, new BigDecimal(lastvalue).add(new BigDecimal(strValue)));
                    }else{
                        field.set(obj,lastvalue);
                    }
                }

            }
        }
    }

    public Boolean isNumeric(String value) {
        // 定义数字的正则表达式，允许负号和小数点
        String numericRegex = "^[-+]?[0-9]*\\.?[0-9]+$";
        // 创建 Pattern 对象
        Pattern pattern = Pattern.compile(numericRegex);
        // 创建 Matcher 对象
        Matcher matcher = pattern.matcher(value);
        // 判断是否匹配
        if(!matcher.matches()){
            return false;
        }
        return true;
    }
}
